#include <arch/io.h>
#include <arch/cpu/soc/s3c2440.h>

#ifdef __TOP_HALF__
#include <th/drivers/nand_chip.h>
#include <th/drivers/clock.h>
#include <th/lib/nand.h>
#endif

#ifdef __TOP_HALF__ 

#define s3c2440_hwcontrol	nand_chip_cmd_ctrl 
#define s3c2440_dev_ready	nand_chip_dev_ready

void nand_chip_read_buf(struct mtd_info *mtd, uint8_t* buf, int len)
{
	int i;	
	struct s3c2440_nand *nand = s3c2440_get_base_nandctl();

	for (i = 0; i < len; i++) {
		buf[i] = readb(&nand->nfdata);
	}
}

#endif

void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
	struct s3c2440_nand *nand = s3c2440_get_base_nandctl();

	if (ctrl & NAND_CTRL_CHANGE) {
		if (ctrl & NAND_NCE) {
			writel(readl(&nand->nfcont) & ~2, &nand->nfcont);
		} else {
			writel(readl(&nand->nfcont) | 2, &nand->nfcont);
		}
	}

	if (cmd != NAND_CMD_NONE) {
		if (ctrl & NAND_CLE) {
			writeb((uint8_t)cmd, &nand->nfcmd);
		} else if (ctrl & NAND_ALE) {
			writeb((uint8_t)cmd, &nand->nfaddr);
		}
	}
}

int s3c2440_dev_ready(struct mtd_info *mtd)
{
	struct s3c2440_nand *nand = s3c2440_get_base_nandctl();

	return readl(&nand->nfstat) & 1;
}

#ifndef __TOP_HALF__ 
static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
}

static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code)
{
}

static int s3c2440_nand_correct_data(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc)
{
}
#endif

int nand_chip_init(void)
{
	uint32_t tmp;
	struct s3c2440_nand *nand = s3c2440_get_base_nandctl();
	
	clock_enable(CLOCK_NAND);
	
	tmp  = readl(&nand->nfconf);
	tmp &= ~((7 << 4) | (7 << 8) | (3 << 12));
	tmp |= (1 << 4) | (3 << 8) | (0 << 12);
	writel(tmp, &nand->nfconf);

	writel(3, &nand->nfcont);

#ifndef __TOP_HALF__ 
	nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
	nand->IO_ADDR_W = (void *)&nand_reg->nfdata;
	nand->select_chip = NULL;	
	nand->cmd_ctrl = ;
	nand->ecc.hwctl = ;
	nand->ecc.calculate = ;
	nand->ecc.correct = ;
	nand->ecc.mode = ;
	nand->ecc.size = ;
	nand->ecc.bytes = ;
	nand->options = ;
#endif

	return 0;
}

